package com.xjy.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xjy.common.exception.CustomException;
import com.xjy.common.exception.UtilException;
import com.xjy.common.utils.PageUtils;
import com.xjy.common.core.page.PagePlus;
import com.xjy.common.core.page.TableDataInfo;
import com.xjy.system.domain.SysCreditAdvance;
import com.xjy.system.domain.SysMaterialMng;
import com.xjy.system.domain.bo.*;
import com.xjy.system.domain.vo.SysMaterialMngVo;
import com.xjy.system.domain.vo.SysMaterialUpdateVo;
import com.xjy.system.mapper.SysMaterialMngMapper;
import com.xjy.system.service.ISysDeptService;
import com.xjy.system.service.ISysMaterialMngService;
import com.xjy.system.service.ISysStaffService;
import net.sf.jsqlparser.util.deparser.GroupByDeParser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xjy.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjy.system.domain.SysMaterialUpdate;
import com.xjy.system.mapper.SysMaterialUpdateMapper;
import com.xjy.system.service.ISysMaterialUpdateService;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 物料管理变更信息Service业务层处理
 *
 * @author zc
 * @date 2022-01-30
 */
@Service
public class SysMaterialUpdateServiceImpl extends ServicePlusImpl<SysMaterialUpdateMapper, SysMaterialUpdate> implements ISysMaterialUpdateService {

	@Autowired
	ISysMaterialMngService iSysMaterialMngService;
	@Autowired
	SysMaterialMngMapper sysMaterialMngMapper;
	@Autowired
	ISysStaffService iSysStaffService;
	@Autowired
	private ISysDeptService deptService;

	@Override
	public SysMaterialUpdateVo queryById(Long id) {
		SysMaterialUpdateVo rsp = null;
		SysMaterialUpdateQueryBo bo = new SysMaterialUpdateQueryBo();
		bo.setId(id);
		List<SysMaterialUpdateVo> list = baseMapper.queryPageList(bo);
		if (null != list && list.size() > 0) {
			rsp = list.get(0);
		}

		//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
		String materialStatus = rsp.getMaterialStatus();
		if("2".equals(materialStatus)){
			rsp.setLendList(new ArrayList<>());
			String reserveOne = rsp.getReserveOne();
			if(StringUtils.isNotBlank(reserveOne)){
				JSONArray lendListArr = JSONUtil.parseArray(reserveOne);
				List<SysMaterialUpdateReturnBo> lendList = JSONUtil.toList(lendListArr,SysMaterialUpdateReturnBo.class);
				rsp.setLendList(lendList);
			}



		}


		return rsp;
	}

	@Override
	public TableDataInfo<SysMaterialUpdateVo> queryPageList(SysMaterialUpdateQueryBo bo) {
		PagePlus<SysMaterialUpdate, SysMaterialUpdateVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), SysMaterialUpdateVo.class);
		List<SysMaterialUpdateVo> sysMaterialUpdateVoList = result.getRecordsVo();
		for(SysMaterialUpdateVo sysMaterialUpdateVo:sysMaterialUpdateVoList){
			//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
			String materialStatus = sysMaterialUpdateVo.getMaterialStatus();
			if("2".equals(materialStatus)){
				sysMaterialUpdateVo.setLendList(new ArrayList<>());
				String reserveOne = sysMaterialUpdateVo.getReserveOne();
				if(StringUtils.isNotBlank(reserveOne)){
					JSONArray lendListArr = JSONUtil.parseArray(reserveOne);
					List<SysMaterialUpdateReturnBo> lendList = JSONUtil.toList(lendListArr,SysMaterialUpdateReturnBo.class);
					sysMaterialUpdateVo.setLendList(lendList);
				}



			}
		}
		result.setRecordsVo(sysMaterialUpdateVoList);
		return PageUtils.buildDataInfo(result);
	}

	@Override
	public List<SysMaterialUpdateVo> queryList(SysMaterialUpdateQueryBo bo) {
		List<SysMaterialUpdateVo> rsp =  listVo(buildQueryWrapper(bo), SysMaterialUpdateVo.class);
		for(SysMaterialUpdateVo sysMaterialUpdateVo:rsp){
			//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
			String materialStatus = sysMaterialUpdateVo.getMaterialStatus();
			if("2".equals(materialStatus)){
				sysMaterialUpdateVo.setLendList(new ArrayList<>());
				String reserveOne = sysMaterialUpdateVo.getReserveOne();
				if(StringUtils.isNotBlank(reserveOne)){
					JSONArray lendListArr = JSONUtil.parseArray(reserveOne);
					List<SysMaterialUpdateReturnBo> lendList = JSONUtil.toList(lendListArr,SysMaterialUpdateReturnBo.class);
					sysMaterialUpdateVo.setLendList(lendList);
				}



			}
		}
		return	rsp;
	}

	private LambdaQueryWrapper<SysMaterialUpdate> buildQueryWrapper(SysMaterialUpdateQueryBo bo) {
		Map<String, Object> params = bo.getParams();
		LambdaQueryWrapper<SysMaterialUpdate> lqw = Wrappers.lambdaQuery();
		lqw.eq(StrUtil.isNotBlank(bo.getProjName()), SysMaterialUpdate::getProjName, bo.getProjName());
		lqw.eq(bo.getDeptId() != null, SysMaterialUpdate::getDeptId, bo.getDeptId());
		lqw.eq(bo.getId() != null, SysMaterialUpdate::getId, bo.getId());
		lqw.eq(bo.getProjId() != null, SysMaterialUpdate::getProjId, bo.getProjId());
		lqw.eq(null != bo.getMaterialId(), SysMaterialUpdate::getMaterialId, bo.getMaterialId());
		lqw.eq(bo.getMaterialNo() != null, SysMaterialUpdate::getMaterialNo, bo.getMaterialNo());
		lqw.eq(StrUtil.isNotBlank(bo.getMaterialStatus()), SysMaterialUpdate::getMaterialStatus, bo.getMaterialStatus());
		lqw.like(StrUtil.isNotBlank(bo.getMaterialAffiliatedOddNo()), SysMaterialUpdate::getMaterialAffiliatedOddNo, bo.getMaterialAffiliatedOddNo());
		lqw.eq(bo.getNum() != null, SysMaterialUpdate::getNum, bo.getNum());
		lqw.eq(bo.getUpdateTime() != null, SysMaterialUpdate::getUpdateTime, bo.getUpdateTime());
		lqw.eq(StrUtil.isNotBlank(bo.getRemark()), SysMaterialUpdate::getRemark, bo.getRemark());
		lqw.eq(StrUtil.isNotBlank(bo.getHandler()), SysMaterialUpdate::getHandler, bo.getHandler());
		lqw.eq(bo.getHandlerId() != null, SysMaterialUpdate::getHandlerId, bo.getHandlerId());
		lqw.eq(StrUtil.isNotBlank(bo.getReserveOne()), SysMaterialUpdate::getReserveOne, bo.getReserveOne());
		lqw.eq(StrUtil.isNotBlank(bo.getReserveTwo()), SysMaterialUpdate::getReserveTwo, bo.getReserveTwo());
		lqw.eq(StrUtil.isNotBlank(bo.getReserveThree()), SysMaterialUpdate::getReserveThree, bo.getReserveThree());
		lqw.eq(bo.getCreateTime() != null, SysMaterialUpdate::getCreateTime, bo.getCreateTime());
		lqw.eq(bo.getDelFlag() != null, SysMaterialUpdate::getDelFlag, bo.getDelFlag());
		lqw.eq(bo.getAuditStatus() != null, SysMaterialUpdate::getAuditStatus, bo.getAuditStatus());
		lqw.ge(StrUtil.isNotBlank(bo.getCreateTimeStart()), SysMaterialUpdate::getCreateTime, bo.getCreateTimeStart());
		lqw.le(StrUtil.isNotBlank(bo.getCreateTimeEnd()), SysMaterialUpdate::getCreateTime, bo.getCreateTimeEnd());
		lqw.le(null != bo.getStatus() &&  bo.getStatus() == 1, SysMaterialUpdate::getAvailableStock, 0);
		lqw.gt(null != bo.getStatus() &&  bo.getStatus() == 0, SysMaterialUpdate::getAvailableStock, 0);
		lqw.like(StrUtil.isNotBlank(bo.getMaterialName()), SysMaterialUpdate::getMaterialName, bo.getMaterialName());
		lqw.like(StrUtil.isNotBlank(bo.getHandler()), SysMaterialUpdate::getHandler, bo.getHandler());
		lqw.in(null != bo.getIdList() && bo.getIdList().size() > 0, SysMaterialUpdate::getId, bo.getIdList());

		return lqw;
	}

	@Override
	public Boolean insertByAddBo(SysMaterialUpdateAddBo bo) {
		Long materialId = bo.getMaterialId();
		SysMaterialUpdate add = BeanUtil.toBean(bo, SysMaterialUpdate.class);
		Long num = add.getNum();
		if (null == num || !(num > 0)) {
			throw new UtilException("变更数量必须大于0！");
		}
		if (null == add.getMaterialId()) {
			throw new UtilException("物料ID不能为空！");
		}
		add.setDeptName(deptService.selectDeptById(bo.getDeptId()).getDeptName());
		SysMaterialMngVo sysMaterialMngVo = iSysMaterialMngService.queryById(Long.valueOf(materialId));
		if (null == sysMaterialMngVo) {
			throw new UtilException("未查询到物料主数据！");
		}
		if (!sysMaterialMngVo.getAuditStatus()) {
			throw new UtilException("物料主数据未审批！");
		}

		//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
		String materialStatus = bo.getMaterialStatus();
		if("2".equals(materialStatus)){
			List<SysMaterialUpdateReturnBo> lendList = bo.getLendList();
			if(null == lendList || lendList.size() == 0){
				throw new UtilException("归还物料，必须选择物料借出单据！");
			}
			Long numReturn = 0L;
			for(SysMaterialUpdateReturnBo sysMaterialUpdateReturnBo:lendList){

				numReturn +=sysMaterialUpdateReturnBo.getReturnNum();


			}
			if (null == numReturn || !(numReturn > 0)) {
				throw new UtilException("归还数量总和必须大于0！");
			}
			add.setNum(numReturn);
			List<String>  materialNoList = lendList.stream().map(SysMaterialUpdateReturnBo::getMaterialNo).collect(Collectors.toList());
			JSONArray lendListArr = JSONUtil.parseArray(lendList);
			JSONArray materialNoListArr = JSONUtil.parseArray(materialNoList);
			String materialNoListArrStr = JSONUtil.toJsonStr(materialNoListArr);

			add.setMaterialAffiliatedOddNo(materialNoListArrStr);
			add.setReserveOne(JSONUtil.toJsonStr(lendListArr));






		}


		return save(add);
	}

	private void isnullmater(SysMaterialUpdate add, SysMaterialMngVo sysMaterialMngVo) {
		add.setStartAmt(sysMaterialMngVo.getInitAmt());
		add.setInitAmt(sysMaterialMngVo.getInitAmt() - add.getNum());
		add.setAvailableStock(sysMaterialMngVo.getInitAmt() - add.getNum());
		sysMaterialMngVo.setInitAmt(sysMaterialMngVo.getInitAmt() - add.getNum());
		sysMaterialMngVo.setId(Long.valueOf(add.getMaterialId()));
		iSysMaterialMngService.updateByEditVo(sysMaterialMngVo);
	}

	private void mater(SysMaterialUpdate add, SysMaterialMngVo sysMaterialMngVo, List<SysMaterialUpdate> list) {
		list.stream().limit(1).forEach(i -> {
			add.setStartAmt(i.getInitAmt());
			add.setInitAmt(i.getInitAmt() - add.getNum());
			add.setAvailableStock(i.getAvailableStock() - add.getNum());
			sysMaterialMngVo.setInitAmt(i.getInitAmt() - add.getNum());
			sysMaterialMngVo.setId(Long.valueOf(add.getMaterialId()));
			iSysMaterialMngService.updateByEditVo(sysMaterialMngVo);
		});
	}

	@Transactional
	@Override
	public Boolean updateByEditBo(SysMaterialUpdateEditBo bo) {
		Long materialId = bo.getMaterialId();
		SysMaterialUpdate update = BeanUtil.toBean(bo, SysMaterialUpdate.class);
		Long num = update.getNum();
		if (null == num || !(num > 0)) {
			throw new UtilException("变更数量必须大于0！");
		}
		if (null == update.getMaterialId()) {
			throw new UtilException("物料ID不能为空！");
		}

		SysMaterialMngVo sysMaterialMngVo = iSysMaterialMngService.queryById(Long.valueOf(materialId));
		if (null == sysMaterialMngVo) {
			throw new UtilException("未查询到物料主数据！");
		}

		//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
		String materialStatus = bo.getMaterialStatus();
		if("2".equals(materialStatus)){
			List<SysMaterialUpdateReturnBo> lendList = bo.getLendList();
			if(null == lendList || lendList.size() == 0){
				throw new UtilException("归还物料，必须选择物料借出单据！");
			}
			Long numReturn = 0L;
			for(SysMaterialUpdateReturnBo sysMaterialUpdateReturnBo:lendList){

				numReturn +=sysMaterialUpdateReturnBo.getReturnNum();


			}
			if (null == numReturn || !(numReturn > 0)) {
				throw new UtilException("归还数量总和必须大于0！");
			}
			update.setNum(numReturn);
			List<String>  materialNoList = lendList.stream().map(SysMaterialUpdateReturnBo::getMaterialNo).collect(Collectors.toList());
			JSONArray lendListArr = JSONUtil.parseArray(lendList);
			JSONArray materialNoListArr = JSONUtil.parseArray(materialNoList);
			String materialNoListArrStr = JSONUtil.toJsonStr(materialNoListArr);

			update.setMaterialAffiliatedOddNo(materialNoListArrStr);
			update.setReserveOne(JSONUtil.toJsonStr(lendListArr));






		}
		return updateById(update);
	}

	@Transactional
	@Override
	public Boolean auditByEditBo(BaseAuditBo bo) {
		boolean rsp = false;
		List<Long> idList = bo.getIdList();
		SysMaterialUpdateQueryBo sysMaterialUpdateQueryBo = new SysMaterialUpdateQueryBo();
		sysMaterialUpdateQueryBo.setIdList(idList);
		sysMaterialUpdateQueryBo.setAuditStatus(false);
		List<SysMaterialUpdateVo> sysMaterialUpdateVoList = this.queryList(sysMaterialUpdateQueryBo);
		if(null == sysMaterialUpdateVoList || sysMaterialUpdateVoList.size() == 0){
			throw new CustomException("勾选的数据审核状态已审批，无需重新审批！");
		}
		for (SysMaterialUpdateVo sysMaterialUpdateAudit : sysMaterialUpdateVoList) {
			if(!sysMaterialUpdateAudit.getAuditStatus()){
				Long materialId = sysMaterialUpdateAudit.getMaterialId();
				//物料详情
				SysMaterialMngVo sysMaterialMngVo = iSysMaterialMngService.queryById(Long.valueOf(materialId));
				//物料初始库存
				Long startAmt = sysMaterialMngVo.getStartAmt();
				//物料可用库存
				Long initAmt = sysMaterialMngVo.getInitAmt();
				//物料账面库存
				Long availableStock = sysMaterialMngVo.getAvailableStock();

				Long id = sysMaterialUpdateAudit.getId();
				//变更数量
				Long num = sysMaterialUpdateAudit.getNum();
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				String materialStatus = sysMaterialUpdateAudit.getMaterialStatus();
				SysMaterialMng sysMaterialMng = new SysMaterialMng();
				SysMaterialUpdate update = new SysMaterialUpdate();
				sysMaterialMng.setId(sysMaterialMngVo.getId());
				update.setId(id);
				update.setAuditStatus(true);
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				if ("0".equals(materialStatus)) {
					//期初库存
					update.setStartAmt(availableStock);
					//可用库存+
					update.setInitAmt(availableStock + num);
					//账面库存+
					update.setAvailableStock(availableStock + num);


					sysMaterialMng.setInitAmt(initAmt + num);
					sysMaterialMng.setAvailableStock(availableStock + num);
				}
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				if ("1".equals(materialStatus)) {
					//物料可用库存 -
					initAmt = initAmt - num;
					if (initAmt < 0) {
						throw new UtilException("借出数量不能超过实际库存！");
					}
					//期初库存
					update.setStartAmt(availableStock);
					//归还数量 0
					update.setInitAmt(0L);
					//剩余数量
					update.setAvailableStock(num);

					//更新物料信息 物料可用-
					sysMaterialMng.setInitAmt(initAmt);

				}
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				if ("2".equals(materialStatus)) {
					List<SysMaterialUpdateReturnBo> lendList = sysMaterialUpdateAudit.getLendList();
					if(null == lendList || lendList.size() == 0){
						throw new UtilException("审核时，未查询到该归还单据关联的借出单！"+sysMaterialUpdateAudit.getMaterialNo());
					}

					for(SysMaterialUpdateReturnBo sysMaterialUpdateReturnBo:lendList){
						String materialNo = sysMaterialUpdateReturnBo.getMaterialNo();
						SysMaterialUpdateQueryBo sysMaterialUpdateQueryReq = new SysMaterialUpdateQueryBo();
						sysMaterialUpdateQueryReq.setMaterialNo(materialNo);
						sysMaterialUpdateQueryReq.setMaterialStatus("1");
						sysMaterialUpdateQueryReq.setAuditStatus(true);
						sysMaterialUpdateQueryReq.setMaterialId(materialId);
						List<SysMaterialUpdateVo> lendDetailList = this.queryList(sysMaterialUpdateQueryReq);
						if (null == lendDetailList || lendDetailList.size() != 1) {
							throw new UtilException("未查询到借出单数据！" + materialNo);
						}
						SysMaterialUpdateVo lend = lendDetailList.get(0);
						SysMaterialUpdate lendUpdate = new SysMaterialUpdate();
						lendUpdate.setId(lend.getId());
						//借出时数量
						Long numLend = lend.getNum();
						//归还数量
						Long initAmtLend = lend.getInitAmt();
						//计算剩余数量
						Long availableStockLend = lend.getAvailableStock();

						initAmtLend = initAmtLend + sysMaterialUpdateReturnBo.getReturnNum();
						availableStockLend = availableStockLend -  sysMaterialUpdateReturnBo.getReturnNum();
						if (initAmtLend > numLend || availableStockLend < 0) {
							throw new UtilException("归还数量不能大于借出时数量！");
						}
						//更新归还数量
						lendUpdate.setInitAmt(initAmtLend);
						//更新剩余数量
						lendUpdate.setAvailableStock(availableStockLend);
						//更新借出信息
						baseMapper.updateById(lendUpdate);

					}
					//期初库存
					update.setStartAmt(availableStock);
					//可用库存
					update.setInitAmt(availableStock + num);
					//账面库存=
					update.setAvailableStock(availableStock);


					//更新物料信息 物料可用+
					sysMaterialMng.setInitAmt(initAmt + num);




				}
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				if ("3".equals(materialStatus)) {
					//期初库存
					update.setStartAmt(availableStock);
					//可用库存 -
					update.setInitAmt(availableStock - num);
					//账面库存 -
					update.setAvailableStock(availableStock - num);

					//更新物料信息 物料可用-，账面-
					initAmt = initAmt - num;
					availableStock = availableStock - num;
					if (availableStock < 0) {
						throw new UtilException("报损数量不能大于可用数量！");
					}
					sysMaterialMng.setInitAmt(initAmt);
					sysMaterialMng.setAvailableStock(availableStock);
				}
				//类型:0:入库,1:借出,2:归还,3:报损,4:售卖
				if ("4".equals(materialStatus)) {
					//期初库存
					update.setStartAmt(availableStock);
					//可用库存 -
					update.setInitAmt(availableStock - num);
					//账面库存 -
					update.setAvailableStock(availableStock - num);

					//更新物料信息 物料可用-，账面-
					initAmt = initAmt - num;
					availableStock = availableStock - num;
					if (availableStock < 0) {
						throw new UtilException("售卖数量不能大于可用数量！");
					}
					sysMaterialMng.setInitAmt(initAmt);
					sysMaterialMng.setAvailableStock(availableStock);
				}

				sysMaterialMngMapper.update(sysMaterialMng);
				rsp = updateById(update);
			}


		}


		return rsp;
	}

	/**
	 * 保存前的数据校验
	 *
	 * @param entity 实体类数据
	 */
	private void validEntityBeforeSave(SysMaterialUpdate entity) {
		//TODO 做一些数据校验,如唯一约束
	}

	@Override
	public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
		if (isValid) {
			//TODO 做一些业务上的校验,判断是否需要校验
		}
		return removeByIds(ids);
	}
}
